}
static void
-gtk_sort_list_model_resort (GtkSortListModel *self)
+gtk_sort_list_model_resort (GtkSortListModel *self,
+ guint already_sorted)
{
- gtk_tim_sort (sort_array_get_data (&self->items),
- sort_array_get_size (&self->items),
- sizeof (SortItem),
- sort_func,
- self->sorter);
+ GtkTimSort sort;
+
+ gtk_tim_sort_init (&sort,
+ sort_array_get_data (&self->items),
+ sort_array_get_size (&self->items),
+ sizeof (SortItem),
+ sort_func,
+ self->sorter);
+ gtk_tim_sort_set_runs (&sort, (gsize[2]) { already_sorted, 0 });
+
+ while (gtk_tim_sort_step (&sort));
+
+ gtk_tim_sort_finish (&sort);
}
static void
{
sort_array_append (&self->items, &(SortItem) { g_list_model_get_item (self->model, i), i });
}
- gtk_sort_list_model_resort (self);
+ gtk_sort_list_model_resort (self, sort_array_get_size (&self->items) - added);
for (i = 0; i < start; i++)
{
else if (sort_array_is_empty (&self->items))
gtk_sort_list_model_create_items (self);
- gtk_sort_list_model_resort (self);
+ gtk_sort_list_model_resort (self, 0);
n_items = g_list_model_get_n_items (G_LIST_MODEL (self));
if (n_items > 1)
added = g_list_model_get_n_items (model);
gtk_sort_list_model_create_items (self);
- gtk_sort_list_model_resort (self);
+ gtk_sort_list_model_resort (self, 0);
}
else
added = 0;
/* Push run onto pending-run stack, and maybe merge */
gtk_tim_sort_push_run (self, self->base, run_len);
- /* Advance to find next run */
- self->base = ELEM (self->base, run_len);
- self->size -= run_len;
-
return TRUE;
}
gsize len)
{
g_assert (self->pending_runs < GTK_TIM_SORT_MAX_PENDING);
+ g_assert (len <= self->size);
self->run[self->pending_runs].base = base;
self->run[self->pending_runs].len = len;
self->pending_runs++;
+
+ /* Advance to find next run */
+ self->base = ((char *) self->base) + len * self->element_size;
+ self->size -= len;
}
/**
return self->tmp;
}
+/*<private>
+ * gtk_tim_sort_get_runs:
+ * @self: a #GtkTimSort
+ * @runs: (out) (caller-allocates): Place to store the 0-terminated list of
+ * runs
+ *
+ * Stores the already presorted list of runs - ranges of items that are
+ * known to be sorted among themselves.
+ *
+ * This can be used with gtk_tim_sort_set_runs() when resuming a sort later.
+ **/
+void
+gtk_tim_sort_get_runs (GtkTimSort *self,
+ gsize runs[GTK_TIM_SORT_MAX_PENDING + 1])
+{
+ gsize i;
+
+ g_return_if_fail (self);
+ g_return_if_fail (runs);
+
+ for (i = 0; i < self->pending_runs; i++)
+ runs[i] = self->run[i].len;
+}
+
+/*<private>
+ * gtk_tim_sort_set_runs:
+ * @self: a freshly initialized #GtkTimSort
+ * @runs: (array length=zero-terminated): a 0-terminated list of runs
+ *
+ * Sets the list of runs. A run is a range of items that are already
+ * sorted correctly among themselves. Runs must appear at the beginning of
+ * the array.
+ *
+ * Runs can only be set at the beginning of the sort operation.
+ **/
+void
+gtk_tim_sort_set_runs (GtkTimSort *self,
+ gsize *runs)
+{
+ gsize i;
+
+ g_return_if_fail (self);
+ g_return_if_fail (self->pending_runs == 0);
+
+ for (i = 0; runs[i] != 0; i++)
+ gtk_tim_sort_push_run (self, self->base, runs[i]);
+}
+
#if 1
#define WIDTH 4
#include "gtktimsort-impl.c"
gpointer data);
void gtk_tim_sort_finish (GtkTimSort *self);
+void gtk_tim_sort_get_runs (GtkTimSort *self,
+ gsize runs[GTK_TIM_SORT_MAX_PENDING + 1]);
+void gtk_tim_sort_set_runs (GtkTimSort *self,
+ gsize *runs);
+
gboolean gtk_tim_sort_step (GtkTimSort *self);
void gtk_tim_sort (gpointer base,